﻿using Abp.Domain.Uow;
using GN.Pay.TradeChannel;
using GN.Pay.Utils;
using GN.Pay.GatewayWeb.JumpNotify;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Transactions;
using System.Web;
using System.Web.Mvc;
using GN.Pay.Application.GatewayApp;
using GN.Pay.Application.GatewayApp.Dto.Output;
using GN.Pay.Core.Services;
using System.Threading.Tasks;

namespace GN.Pay.GatewayWeb.Controllers.Notify
{
    /// <summary>
    /// 付款通知控制器抽象
    /// </summary>
    public abstract class APayNotifyController : PayControllerBase
    {
        /// <summary>
        /// 缓存服务
        /// </summary>
        private readonly ITradeCacheService tradeCacheService;

        protected readonly ITradeNotifyAppService tradeNotifyAppService;

        /// <summary>
        /// 实例化 APayNotifyController 类新实例
        /// </summary>
        /// <param name="tradeNotifyAppService"></param>
        public APayNotifyController(ITradeNotifyAppService tradeNotifyAppService)
        {
            this.tradeNotifyAppService = tradeNotifyAppService;
            this.tradeCacheService = IocManagerUtils.IocManager.Resolve<ITradeCacheService>();
        }

        /// <summary>
        /// 获取通道Id
        /// </summary>
        protected abstract string ChannelId { get; }

        /// <summary>
        /// 获取付款通知消息
        /// </summary>
        /// <param name="request">请求</param>
        /// <returns></returns>
        protected abstract NotifyMessage GetPayNotifyMessage(HttpRequestBase request);

        /// <summary>
        /// 获取退款通知消息
        /// </summary>
        /// <param name="request">请求</param>
        /// <returns></returns>
        protected abstract NotifyMessage GetRefundNotifyMessage(HttpRequestBase request);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        protected ITradeChannel GetPayTradeChannel(NotifyMessage message)
        {
            if (message == null)
            {
                return null;
            }
            if (message.Message == null || string.IsNullOrWhiteSpace(message.UniqueNo))
            {
                return null;
            }
            try
            {
                return tradeNotifyAppService.GetPayTradeChannel(message.UniqueNo);
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        protected ITradeChannel GetRefundTradeChannel(NotifyMessage message)
        {
            if (message == null)
            {
                return null;
            }
            if (message.Message == null || string.IsNullOrWhiteSpace(message.UniqueNo))
            {
                return null;
            }
            try
            {
                return tradeNotifyAppService.GetRefundTradeChannel(message.UniqueNo);
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// 是否付款通知
        /// </summary>
        /// <param name="uniqueNo">唯一编号</param>
        /// <returns></returns>
        protected bool IsPayNotify(string uniqueNo)
        {
            //存在 Bug ,无法获取通知成功
            return false;
            //try
            //{
            //    return tradeCacheService.IsPayNotify(uniqueNo);
            //}
            //catch
            //{
            //    return false;
            //}
        }

        /// <summary>
        /// 设置付款通知
        /// </summary>
        /// <param name="uniqueNo">唯一编号</param>
        /// <returns></returns>
        protected Task SetPayNotify(string uniqueNo)
        {

            //try
            //{
            //    return Task.Run(() =>
            //    {
            //        tradeCacheService.SetPayNotify(uniqueNo);
            //    });
            //}
            //catch
            //{
            //    return Task.FromResult(0);
            //}

            //存在 Bug ,无法获取通知成功
            return Task.FromResult(0);
        }

        /// <summary>
        /// 字典付款通知
        /// </summary>
        protected void DictionaryPayNotify()
        {
            try
            {
                var msg = GetPayNotifyMessage(Request);
                if (msg == null)
                {
                    Logger.Error("未找到对应的支付交易消息，通知数据格式可能不正确。");
                    return;
                }
                if (string.IsNullOrWhiteSpace(msg.UniqueNo))
                {
                    Logger.Error("未找到对应的支付交易号，通知数据格式可能不正确。");
                    return;
                }
                ITradeChannel channel = GetPayTradeChannel(msg);
                if (channel != null)
                {
                    try
                    {
                        if (!this.IsPayNotify(msg.UniqueNo))
                        {
                            channel.OrderPayNotify(this.tradeNotifyAppService, msg.Message);
                            this.SetPayNotify(msg.UniqueNo);
                        }
                        Response.Write(channel.PayNotifyResponse(true));
                        Response.StatusCode = (int)HttpStatusCode.OK;
                    }
                    catch (Exception err)
                    {
                        Logger.Error(channel.ChannelName + " 付款通知错误", err);
                        Response.Write(channel.PayNotifyResponse(false));
                    }
                }
                else
                {
                    Logger.Error("付款交易号[" + msg.UniqueNo + "]，无对应的申请或账单，无法根据该编号找到对应的交易接口。");
                }
            }
            catch (Exception err)
            {
                Logger.Error("付款通知出错:" + err);
            }
        }

        /// <summary>
        /// 字典退款款通知
        /// </summary>
        protected void DictionaryRefundNotify()
        {
            try
            {
                var msg = GetRefundNotifyMessage(Request);
                if (msg == null)
                {
                    Logger.Error("未找到对应的交易消息，通知数据格式可能不正确。");
                    return;
                }
                if (string.IsNullOrWhiteSpace(msg.UniqueNo))
                {
                    Logger.Error("未找到对应的退款交易编号，通知数据格式可能不正确。");
                    return;
                }
                ITradeChannel channel = GetRefundTradeChannel(msg);
                if (channel != null)
                {
                    try
                    {
                        channel.OrderRefundNotify(this.tradeNotifyAppService, msg.Message);
                        Response.Write(channel.RefundNotifyResponse(true));
                    }
                    catch (Exception err)
                    {
                        Logger.Error(channel.ChannelName + " 退款通知错误", err);
                        Response.Write(channel.RefundNotifyResponse(false));
                    }
                }
                else
                {
                    Logger.Error("退款交易编号[" + msg.UniqueNo + "]，无对应的申请或账单，无法根据该编号找到对应的交易接口。");
                }
            }
            catch (Exception err)
            {
                Logger.Error("退款通知出错:" + err);
            }
        }

        /// <summary>
        /// Xml付款通知
        /// </summary>
        protected void XmlPayNotify()
        {
            var msg = GetPayNotifyMessage(Request);
            ITradeChannel channel = GetPayTradeChannel(msg);
            if (channel != null)
            {
                try
                {
                    channel.OrderPayNotify(this.tradeNotifyAppService, msg.Message);
                    Response.Write(channel.PayNotifyResponse(true));
                }
                catch (Exception err)
                {
                    Logger.Error(channel.ChannelName + " 付款通知错误", err);
                    Response.Write(channel.PayNotifyResponse(false));
                }
            }
            else
            {
                Logger.Error("付款通知错误,无 " + ChannelId + " 实现");
            }
        }

       

        /// <summary>
        /// 返回成功等待
        /// </summary>
        /// <param name="tradeNo">交易号</param>
        /// <returns></returns>
        protected ActionResult ReturnWaitResult(string tradeNo)
        {
            try
            {
                var notify = tradeNotifyAppService.GetCacheTradeNotify(tradeNo);
                if (notify == null)
                {
                    return this.ErrorView();
                }
                var data = notify.GetPayNotifyData();
                if (data == null)
                {
                    return this.ErrorView();
                }
                return View("~/Views/Notify/PayReturnWait.cshtml", data);
            }
            catch (Exception err)
            {
                this.Logger.Error("查询缓存异常", err);
                return this.ErrorView();
            }
        }

        /// <summary>
        /// 返回 Wap 成功等待
        /// </summary>
        /// <param name="tradeNo">交易号</param>
        /// <returns></returns>
        protected ActionResult ReturnWapWaitResult(string tradeNo)
        {
            try
            {
                var notify = tradeNotifyAppService.GetCacheTradeNotify(tradeNo);
                if (notify == null)
                {
                    return this.WapErrorView("返回失败", "无法获取通知信息，若已确认支付请前往订单中心查看(1)。");
                }
                var data = notify.GetPayNotifyData();
                if (data == null)
                {
                    return this.WapErrorView("返回失败", "无法获取通知信息，若已确认支付请前往订单中心查看(2)。");
                }
                return View("~/Views/Notify/WapPayReturnWait.cshtml", data);
            }
            catch (Exception err)
            {
                this.Logger.Error("查询缓存异常", err);
                return this.WapErrorView("返回异常", "无法获取通知信息，若已确认支付请前往订单中心查看(3)。");
            }
        }

        /// <summary>
        /// 订单付款通知
        /// </summary>
        public abstract void OrderPay();

        /// <summary>
        /// 订单退款通知
        /// </summary>
        public abstract void OrderRefund();

        /// <summary>
        /// 订单付款返回
        /// </summary>
        public abstract ActionResult OrderPayReturn();

        /// <summary>
        /// 订单付款 Wap 返回
        /// </summary>
        public abstract ActionResult OrderPayWapReturn();
    }
}